﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Transactions;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Unis.Framework.Core.Log;
using Unis.Framework.Core.Utility;
using Unis.Framework.ORM.BaseDefiniens.Enums;
using Unis.Framework.ORM.Common;
using Unis.Framework.ORM.Emit;
using Unis.Framework.ORM.Mapping;
using Unis.Framework.ORM.Model;
using Unis.Framework.ORM.Persistence;
using Unis.Framework.RuleBase.Exceptions;
using Unis.ORM.DbSql;
using Unis.ORM.Mapping;
using Unis.ORM.Persistence;

namespace Unis.Framework.RuleBase.Common
{
    public class DatabaseExecuteHelper
    {
        // Fields
        private PersistenceManagerHelper _PersistenceHelper = new PersistenceManagerHelper();

        // Methods
        public int ExecByStoreProcedure(string storeProcedureName, SqlParamInfo[] sqlParInfos)
        {
            return this.ExecByStoreProcedure(null, storeProcedureName, sqlParInfos);
        }

        public int ExecByStoreProcedure(DbTransaction dbTran, string storeProcedureName, SqlParamInfo[] sqlParInfos)
        {
            Database db = DatabaseHelper.CreateDatabase();
            int num = 0;
            DbCommand storedProcCommand = db.GetStoredProcCommand(storeProcedureName);
            if ((sqlParInfos != null) && (sqlParInfos.Length > 0))
            {
                foreach (SqlParamInfo info in sqlParInfos)
                {
                    if (info.Direction == ParameterDirection.Input)
                    {
                        this._PersistenceHelper.AddParamInfoToDbCommand(db, storedProcCommand, info);
                    }
                    else if (info.Direction == ParameterDirection.Output)
                    {
                        this._PersistenceHelper.AddParamInfoToDbCommand(db, storedProcCommand, info);
                    }
                }
            }
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, storedProcCommand));
                num = (dbTran == null) ? db.ExecuteNonQuery(storedProcCommand) : db.ExecuteNonQuery(storedProcCommand, dbTran);
                if ((sqlParInfos != null) && (sqlParInfos.Length > 0))
                {
                    foreach (SqlParamInfo info2 in sqlParInfos)
                    {
                        if (info2.Direction == ParameterDirection.Output)
                        {
                            info2.Value = db.GetParameterValue(storedProcCommand, info2.Name);
                        }
                    }
                }
                return num;
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException("ExecByStoreProcedure 出错！", exception);
            }
            finally
            {
                storedProcCommand.Dispose();
            }
            return num;
        }
        /// <summary>
        /// 调用存储过程取得返回的Table数据集
        /// </summary>
        /// <param name="procName">存储过程名称</param>
        /// <param name="parameterValues">存储过程参数</param>
        /// <returns>数据集</returns>
        public DataSet ExecByStoreProcedure(string procName, List<ProcInParas> parameterValues)
        {
            try
            {
                Database db = DatabaseHelper.CreateDatabase();

                DbCommand dc = db.GetStoredProcCommand(procName);

                TraceEx.Write("正在执行存储过程:" + procName);

                if (parameterValues != null && parameterValues.Count > 0)
                {
                    string record = "";
                    foreach (var item in parameterValues)
                    {
                        db.AddInParameter(dc, item.Name, item.Dbtype, item.Value);
                        record += String.Format("参数名:{0},参数类型:{1},参数值:{2}；",item.Name,item.Dbtype,item.Value);
                    }
                    TraceEx.Write("存储过程参数明细:" + record);
                }
                DataSet ds = db.ExecuteDataSet(dc);
                return ds;
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException("ExecByStoreProcedure 出错！", exception);
            }
        }
        public DataSet ExecuteDataSet(Database db, DbCommand dbCmd)
        {
            return this.ExecuteDataSet(db, dbCmd, null);
        }

        public DataSet ExecuteDataSet(string sqlString, List<SqlParamInfo> sqlParams)
        {
            return this.ExecuteDataSet(sqlString, sqlParams, null);
        }

        public DataSet ExecuteDataSet(Database db, DbCommand dbCmd, DbTransaction transaction)
        {
            DataSet set = null;
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, dbCmd));
                set = (transaction == null) ? db.ExecuteDataSet(dbCmd) : db.ExecuteDataSet(dbCmd, transaction);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                dbCmd.Dispose();
            }
            return set;
        }

        public DataSet ExecuteDataSet(string sqlString, List<SqlParamInfo> sqlParams, DbTransaction transaction)
        {
            DataSet set;
            Database db = DatabaseHelper.CreateDatabase();
            DbCommand sqlStringCommand = db.GetSqlStringCommand(sqlString);
            sqlStringCommand.CommandText = this._PersistenceHelper.ReplaceSqlParamsByDatabaseType(db, sqlStringCommand.CommandText);
            if ((sqlParams != null) && (sqlParams.Count > 0))
            {
                foreach (SqlParamInfo info in sqlParams)
                {
                    this._PersistenceHelper.AddParamInfoToDbCommand(db, sqlStringCommand, info);
                }
            }
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, sqlStringCommand));
                set = (transaction == null) ? db.ExecuteDataSet(sqlStringCommand) : db.ExecuteDataSet(sqlStringCommand, transaction);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                sqlStringCommand.Dispose();
            }
            return set;
        }

        public int ExecuteNonQuery(Database db, DbCommand dbCmd)
        {
            return this.ExecuteNonQuery(db, new DbCommand[] { dbCmd });
        }

        public int ExecuteNonQuery(Database db, DbCommand[] dbCmds)
        {
            return this.ExecuteNonQuery(db, dbCmds, TransactionScopeOption.Required);
        }

        public int ExecuteNonQuery(string sqlString, List<SqlParamInfo> sqlParams)
        {
            int num;
            Database db = DatabaseHelper.CreateDatabase();
            DbCommand sqlStringCommand = db.GetSqlStringCommand(sqlString);
            sqlStringCommand.CommandText = this._PersistenceHelper.ReplaceSqlParamsByDatabaseType(db, sqlStringCommand.CommandText);
            if ((sqlParams != null) && (sqlParams.Count > 0))
            {
                foreach (SqlParamInfo info in sqlParams)
                {
                    this._PersistenceHelper.AddParamInfoToDbCommand(db, sqlStringCommand, info);
                }
            }
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, sqlStringCommand));
                num = db.ExecuteNonQuery(sqlStringCommand);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                sqlStringCommand.Dispose();
            }
            return num;
        }

        public int ExecuteNonQuery(Database db, DbCommand[] dbCmds, DbTransaction transaction)
        {
            int num = 0;
            DatabaseType databaseType = DatabaseConfigurationScope.GetDatabaseType(db);
            try
            {
                foreach (DbCommand command in dbCmds)
                {
                    try
                    {
                        if (databaseType == DatabaseType.Oracle)
                        {
                            command.CommandText = this._PersistenceHelper.RemoveSqlStringLastSemicolon(db, command.CommandText);
                        }
                        TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, command));
                        num += (transaction == null) ? db.ExecuteNonQuery(command) : db.ExecuteNonQuery(command, transaction);
                    }
                    catch (Exception exception)
                    {
                        throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
                    }
                }
            }
            catch (DatabaseExecuteException exception2)
            {
                throw exception2;
            }
            catch (Exception exception3)
            {
                throw exception3;
            }
            finally
            {
                try
                {
                    foreach (DbCommand command2 in dbCmds)
                    {
                        command2.Dispose();
                    }
                }
                catch
                {
                }
            }
            return num;
        }

        public int ExecuteNonQuery(Database db, DbCommand[] dbCmds, TransactionScopeOption transactionScope)
        {
            int num = 0;
            DatabaseType databaseType = DatabaseConfigurationScope.GetDatabaseType(db);
            using (TransactionScope scope = new TransactionScope(transactionScope))
            {
                try
                {
                    foreach (DbCommand command in dbCmds)
                    {
                        try
                        {
                            if (databaseType == DatabaseType.Oracle)
                            {
                                command.CommandText = this._PersistenceHelper.RemoveSqlStringLastSemicolon(db, command.CommandText);
                            }
                            TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, command));
                            num += db.ExecuteNonQuery(command);
                        }
                        catch (Exception exception)
                        {
                            throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
                        }
                    }
                    scope.Complete();
                }
                catch (DatabaseExecuteException exception2)
                {
                    throw exception2;
                }
                catch (Exception exception3)
                {
                    throw exception3;
                }
                finally
                {
                    try
                    {
                        foreach (DbCommand command2 in dbCmds)
                        {
                            command2.Dispose();
                        }
                    }
                    catch
                    {
                    }
                }
                return num;
            }
        }

        public IDataReader ExecuteReader(string sqlString)
        {
            return this.ExecuteReader(sqlString, null);
        }

        public IDataReader ExecuteReader(Database db, DbCommand dbCmd)
        {
            IDataReader reader = null;
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, dbCmd));
                reader = db.ExecuteReader(dbCmd);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                dbCmd.Dispose();
            }
            return reader;
        }

        public IDataReader ExecuteReader(string sqlString, DbTransaction transaction)
        {
            IDataReader reader;
            Database db = DatabaseHelper.CreateDatabase();
            DbCommand sqlStringCommand = db.GetSqlStringCommand(sqlString);
            sqlStringCommand.CommandText = this._PersistenceHelper.ReplaceSqlParamsByDatabaseType(db, sqlStringCommand.CommandText);
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, sqlStringCommand));
                reader = db.ExecuteReader(sqlStringCommand);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                sqlStringCommand.Dispose();
            }
            return reader;
        }

        public object ExecuteScalar(Database db, DbCommand dbCmd)
        {
            return this.ExecuteScalar(db, dbCmd, null);
        }

        public object ExecuteScalar(Database db, DbCommand dbCmd, DbTransaction transaction)
        {
            object obj2 = null;
            try
            {
                TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, dbCmd));
                obj2 = (transaction == null) ? db.ExecuteScalar(dbCmd) : db.ExecuteScalar(dbCmd, transaction);
            }
            catch (Exception exception)
            {
                throw new DatabaseExecuteException(" 数据执行SQL 语句 出错！", exception);
            }
            finally
            {
                dbCmd.Dispose();
            }
            return obj2;
        }

        public List<T> GetObjects<T>(DbTransaction transaction, Type cfgEntityType, string sqlString, List<SqlParamInfo> sqlParams)
        {
            Database db = DatabaseHelper.CreateDatabase();
            if (this._PersistenceHelper == null)
            {
                this._PersistenceHelper = new PersistenceManagerHelper();
            }
            DbCommand sqlStringCommand = db.GetSqlStringCommand(sqlString);
            sqlStringCommand.CommandText = this._PersistenceHelper.ReplaceSqlParamsByDatabaseType(db, sqlStringCommand.CommandText);
            if ((sqlParams != null) && (sqlParams.Count > 0))
            {
                foreach (SqlParamInfo info in sqlParams)
                {
                    this._PersistenceHelper.AddParamInfoToDbCommand(db, sqlStringCommand, info);
                }
            }
            DbCommand dbCmd = sqlStringCommand;
            Type t = cfgEntityType;
            bool flag = t.IsSubclassOf(typeof(BaseModel));
            ModelMappingInfo modelMappingInfo = AttMappingManager.Instance.GetModelMappingInfo(t);
            List<T> list = new List<T>();
            TraceEx.Write("正在执行:" + DbCommandExecuteTrack.Instance.CommandToTrackMessage(db, dbCmd));
            using (IDataReader reader = (transaction == null) ? db.ExecuteReader(dbCmd) : db.ExecuteReader(dbCmd, transaction))
            {
                try
                {
                    try
                    {
                        DataTable schemaTable = reader.GetSchemaTable();
                        Dictionary<string, DynamicPropertyAccessor> dictionary = new Dictionary<string, DynamicPropertyAccessor>();
                        foreach (FieldPropertyInfo info3 in modelMappingInfo.FieldPropertys.Values)
                        {
                            if (schemaTable.Select(string.Format("ColumnName='{0}'", info3.FieldName)).Length > 0)
                            {
                                PropertyInfo property = t.GetProperty(info3.PropertyName);
                                if (property != null)
                                {
                                    DynamicPropertyAccessor accessor = new DynamicPropertyAccessor(t, property);
                                    dictionary.Add(info3.FieldName, accessor);
                                }
                            }
                        }
                        if (dictionary.Count > 0)
                        {
                            while (reader.Read())
                            {
                                T target = (T)Reflection.CreateObjectInstance(t);
                                foreach (KeyValuePair<string, DynamicPropertyAccessor> pair in dictionary)
                                {
                                    if (reader[pair.Key] != DBNull.Value)
                                    {
                                        dictionary[pair.Key].Set(target, reader[pair.Key]);
                                    }
                                }
                                if (flag)
                                {
                                    BaseModel model = target as BaseModel;
                                    model.EntityState = EntityState.Persistent;
                                }
                                list.Add(target);
                            }
                        }
                        return list;
                    }
                    catch (Exception exception)
                    {
                        throw new DatabaseExecuteException("执行GetObjectsByXml<" + t.FullName + "> 出错！", exception);
                    }
                    return list;
                }
                finally
                {
                    dbCmd.Dispose();
                }
            }
            return list;
        }

        // Properties
        public static DatabaseExecuteHelper NewInstance
        {
            get
            {
                return new DatabaseExecuteHelper();
            }
        }
    }

}
